package com.lzh.shijicloudstack.utils;

import cn.hutool.core.util.StrUtil;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author luzhiheng
 * @date 2024-08-19
 */
public class DateUtil {

    private static final String DATE_PATTERN_YMD = "yyyyMMdd";
    private static final String DATE_PATTERN = "yyyy-MM-dd";
    private static final String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    private static final String MONTH_PATTERN = "yyyy-MM";

    /**
     * 格式化日期
     *
     * @param date 日期
     * @return 格式化后的日期字符串
     */
    public String formatDateYMd(Date date) {
        if (date == null) {
            return "";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_PATTERN_YMD);
        try {
            return sdf.format(date);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 格式化日期
     *
     * @param date 日期
     * @return 格式化后的日期字符串
     */
    public String formatMonth(Date date) {
        if (date == null) {
            return "";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(MONTH_PATTERN);
        try {
            return sdf.format(date);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 格式化日期
     *
     * @param date 日期
     * @return 格式化后的日期字符串
     */
    public String formatDate(Date date) {
        if (date == null) {
            return "";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_PATTERN);
        try {
            return sdf.format(date);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 格式化日期
     *
     * @param localDate 日期
     * @return 格式化后的日期字符串
     */
    public String formatDate(LocalDate localDate) {
        if (localDate == null) {
            return "";
        }
        DateTimeFormatter pattern = DateTimeFormatter.ofPattern(DATE_PATTERN);
        try {
            return localDate.format(pattern);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 格式化日期
     *
     * @param localDateTime 日期
     * @return 格式化后的日期字符串
     */
    public String formatDate(LocalDateTime localDateTime) {
        if (localDateTime == null) {
            return "";
        }
        DateTimeFormatter pattern = DateTimeFormatter.ofPattern(DATE_PATTERN);
        try {
            return localDateTime.format(pattern);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 格式化日期时间
     *
     * @param date 日期
     * @return 格式化后的日期时间字符串
     */
    public String formatDateTime(Date date) {
        if (date == null) {
            return "";
        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(DATETIME_PATTERN);
            return sdf.format(date);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 格式化日期时间
     *
     * @param localDateTime 日期
     * @return 格式化后的日期时间字符串
     */
    public String formatDateTime(LocalDateTime localDateTime) {
        if (localDateTime == null) {
            return "";
        }
        DateTimeFormatter pattern = DateTimeFormatter.ofPattern(DATETIME_PATTERN);
        try {
            return localDateTime.format(pattern);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 根据指定格式格式化日期
     *
     * @param date   日期
     * @param format 格式
     * @return 格式化后的日期字符串
     */
    public String format(Date date, String format) {
        if (date == null) {
            return "";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        try {
            return sdf.format(date);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 解析日期时间
     *
     * @param datetimeStr 日期字符串
     * @return 日期
     */
    public Date parseDatetime(String datetimeStr) {
        SimpleDateFormat sdf = new SimpleDateFormat(DATETIME_PATTERN);
        Date date = null;
        try {
            date = sdf.parse(datetimeStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return date;
    }

    /**
     * 解析日期
     *
     * @param dateStr 日期字符串
     * @return 日期
     */
    public Date parseDate(String dateStr) {
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_PATTERN);
        try {
            return sdf.parse(dateStr);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 解析日期
     *
     * @param dateStr 日期字符串
     * @return 日期
     */
    public Date parse(String dateStr, String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        try {
            return sdf.parse(dateStr);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 将mybatis返回的类型统一成Date
     *
     * @param obj 原始datetime对象
     * @return Date类型
     */
    public Date getDate(Object obj) {
        if (obj == null) {
            return null;
        } else if (obj instanceof Date) {
            return (Date) obj;
        } else if (obj instanceof LocalDate) {
            return Date.from(((LocalDate) obj).atStartOfDay(ZoneOffset.ofHours(8)).toInstant());
        } else if (obj instanceof LocalDateTime) {
            return Date.from(((LocalDateTime) obj).atZone(ZoneOffset.ofHours(8)).toInstant());
        } else if (obj instanceof String) {
            Date date = null;
            String s = (String) obj;
            try {
                s = s.replaceAll("\\s+", " ").trim();
                date = new SimpleDateFormat(DATETIME_PATTERN).parse(s);
            } catch (Exception ignored) {
                // 这里使用兼容性更高的函数来试一下
                try {
                    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                            .appendPattern(DATE_PATTERN)
                            .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
                            .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
                            .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
                            .parseDefaulting(ChronoField.MILLI_OF_SECOND, 0)
                            .toFormatter();
                    LocalDateTime warrantyDate = LocalDateTime.parse(s, formatter);
                    date = Date.from(warrantyDate.atZone(ZoneOffset.ofHours(8)).toInstant());
                } catch (Exception ignored2) {
                }
            }
            return date;
        } else {
            return null;
        }
    }

    /**
     * 计算两个日期之间相差的秒数
     *
     * @param beginDate 开始日期
     * @param endDate   结束日期
     * @return 相差的秒数
     */
    public long subSecondsByDate(Date beginDate, Date endDate) {
        if (beginDate == null || endDate == null) {
            return 0;
        }
        return (endDate.getTime() - beginDate.getTime()) / 1000;
    }

    /**
     * 计算两个日期之间相差的毫秒数
     *
     * @param beginDate 开始日期
     * @param endDate   结束日期
     * @return 相差的毫秒数
     */
    public long subMillisecondsByDate(Date beginDate, Date endDate) {
        if (beginDate == null || endDate == null) {
            return 0;
        }
        return (endDate.getTime() - beginDate.getTime());
    }

    /**
     * 日期 + n月
     *
     * @param date   日期
     * @param months 月份数
     * @return 日期
     */
    public Date addMonths(Date date, Integer months) {
        if (months == null) {
            months = 0;
        }
        if (date == null) {
            return null;
        }
        Calendar instance = Calendar.getInstance();
        instance.setTime(date);
        instance.add(Calendar.MONTH, months);
        return instance.getTime();
    }

    /**
     * 日期 + n天
     *
     * @param date 日期
     * @param days 天数
     * @return 日期
     */
    public Date addDays(Date date, Integer days) {
        if (days == null) {
            days = 0;
        }
        if (date == null) {
            return null;
        }
        Calendar instance = Calendar.getInstance();
        instance.setTime(date);
        instance.add(Calendar.DAY_OF_YEAR, days);
        return instance.getTime();
    }

    /**
     * 日期 + 秒数
     *
     * @param date    日期
     * @param seconds 秒
     * @return 容器哦
     */
    public Date addSeconds(Date date, int seconds) {
        long milliseconds = date.getTime();
        milliseconds += seconds * 1000L;
        return new Date(milliseconds);
    }

    /**
     * 比较两个日期的大小
     *
     * @param date1 日期
     * @param date2 日期
     * @return
     */
    public int compareByDate(Date date1, Date date2) {
        if (date1 == null) {
            return -1;
        }
        if (date2 == null) {
            return 1;
        }

        String format1 = this.format(date1, "yyyy-MM-dd");
        String format2 = this.format(date2, "yyyy-MM-dd");
        return format1.compareTo(format2);
    }


    public static void main(String[] args) {
        DateUtil dateUtil = new DateUtil();
        System.out.println(dateUtil.format(new Date(), "yyyy-MM-dd 00:00:00"));
    }

    /**
     * 格式化 日期
     *
     * @param datetimeStr datetime 例：2024-10-09 07:12:32
     * @return date 例：2024-10-09
     */
    public String formatDate(String datetimeStr) {
        if (StrUtil.isEmpty(datetimeStr)) {
            return null;
        }
        return datetimeStr.substring(0, Math.min(10, datetimeStr.length()));
    }

    /**
     * 快排
     *
     * @param list  原始列表
     * @param key   排序字段
     * @param low1  开始index
     * @param high1 结束index
     */
    public void sort(List<Map<String, Object>> list, String key, int low1, int high1) {
        // 按照key,升序排序
        int low = low1;
        int high = high1;
        String x = (String) list.get(low).get(key);
        Map<String, Object> temp = list.get(low);
        if (low1 < high1) {
            while (low < high) {
                while (low < high && ((String) list.get(high).get(key)).compareTo(x) > 0) {
                    high--;
                }
                list.set(low, list.get(high));
                while (low < high && ((String) list.get(low).get(key)).compareTo(x) <= 0) {
                    low++;
                }
                list.set(high, list.get(low));
            }
            list.set(low, temp);
            if (low > low1) {
                sort(list, key, low1, low - 1);
            }
            if (high < high1) {
                sort(list, key, low + 1, high1);
            }
        }
    }
}